package org.lex.dbq.view.driver;

import java.io.File;
import java.io.IOException;
import java.util.Set;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.lex.dbq.model.bo.DefaultDriver;
import org.lex.dbq.model.bo.DriverConfig;
import org.lex.dbq.model.service.DriverService;
import org.lex.dbq.model.service.ServiceFactory;
import org.lex.string.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DriverDialog extends Dialog {

	public static void main(String[] args) {
		showAdd(null);
	}

	public static void showAdd(Shell shell) {
		DriverDialog dialog = new DriverDialog(shell);
		dialog.open();
	}

	public static void showEdit(Shell shell, DriverConfig driver) {
		DriverDialog dialog = new DriverDialog(shell);
		if (null != driver) {
			dialog.driver = driver;
		}
		dialog.open();
	}

	// group
	Combo name = null;
	Text website = null;
	// classpath
	ListViewer classpath = null;
	Button addFile = null;
	Button addFolder = null;
	Button remove = null;
	Button listDrivers = null;
	// classame
	Combo className = null;
	// progress
	ProgressBar progress = null;

	// datas
	DriverConfig driver = new DriverConfig();

	private int columns = 1;
	private Logger log = LoggerFactory.getLogger(DriverDialog.class);

	public DriverDialog(Shell parentShell) {
		super(parentShell);
		this.setBlockOnOpen(true);
		this.setShellStyle(SWT.MAX | SWT.RESIZE);
	}

	void addClasspath(File... files) {
		for (File file : files) {
			driver.getClasspath().addLocation(file);
			log.info("Add " + (file.isFile() ? "File" : "Folder") + ": " + file);
		}
		classpath.setInput(driver.getClasspath().getLocations().toArray());
	}

	void selectDriver(String driver) {
		log.debug("Select driver: " + driver);
		Set<DefaultDriver> set = ServiceFactory.getDefaultDriversService().getDrivers(driver);
		String nameText = "";
		String websiteText = "";

		if (false == set.isEmpty()) {
			DefaultDriver first = set.iterator().next();
			nameText = first.getName();
			websiteText = first.getWebsite();

			for (DefaultDriver d : set) {
				String dname = d.getName();
				if (-1 == name.indexOf(dname)) {
					name.add(dname);
				}
			}
		}
		name.setText(nameText);
		website.setText(websiteText);
	}

	@Override
	protected void okPressed() {
		driver.setName(name.getText());
		driver.setClassName(className.getItem(className.getSelectionIndex()));
		driver.setWebsite(website.getText());

		DriverService service = ServiceFactory.getDriverService();
		service.add(driver);
		try {
			service.store();
		} catch (IOException e) {
			e.printStackTrace();
		}
		super.okPressed();
	}

	@Override
	protected void configureShell(Shell shell) {
		super.configureShell(shell);
		shell.setText("Driver");
		shell.setMinimumSize(375, 400);
	}

	@Override
	protected Control createDialogArea(Composite parent) {
		// ui
		this.initializeWidgets(parent);
		// load driver config
		name.setText(driver.getName());
		website.setText(driver.getWebsite());
		addClasspath(driver.getClasspath().getLocations().toArray(new File[0]));

		String cn = driver.getClassName();
		if (false == StringUtils.isNullOrTrimEmpty(cn)) {
			className.add(cn);
			className.select(className.indexOf(cn));
		}
		return parent;
	}

	private void initializeWidgets(Composite parent) {

		GridLayout layout = new GridLayout();
		layout.makeColumnsEqualWidth = false;
		layout.numColumns = columns;

		Composite con = new Composite(parent, SWT.NONE);
		con.setLayout(layout);
		con.setLayoutData(new GridData(GridData.FILL_BOTH));

		this.createDriverGroup(con);
		this.createClasspathPane(con);
		this.createClassNamePane(con);
		// create progress
		GridData d = new GridData(GridData.FILL_HORIZONTAL);
		d.verticalSpan = 1;
		d.horizontalSpan = 1;

		progress = new ProgressBar(con, SWT.SMOOTH | SWT.HORIZONTAL);
		progress.setLayoutData(d);
		progress.setVisible(false);
	}

	private Composite createDriverGroup(Composite parent) {
		GridData d = null;

		d = new GridData(GridData.FILL_HORIZONTAL);
		d.verticalSpan = 1;
		d.horizontalSpan = columns;

		GridLayout groupLayout = new GridLayout();
		groupLayout.makeColumnsEqualWidth = false;
		groupLayout.numColumns = 2;

		Group group = new Group(parent, SWT.SHADOW_ETCHED_IN);
		group.setText("Driver");
		group.setLayoutData(d);
		group.setLayout(groupLayout);
		{
			d = new GridData();
			d.verticalSpan = 1;
			d.horizontalSpan = 1;

			Label label = new Label(group, SWT.NONE);
			label.setText("Name");
			label.setLayoutData(d);

			d = new GridData(GridData.FILL_HORIZONTAL);
			d.verticalSpan = 1;
			d.horizontalSpan = 1;

			name = new Combo(group, SWT.NONE);
			name.setLayoutData(d);
		}
		{
			d = new GridData();
			d.verticalSpan = 1;
			d.horizontalSpan = 1;

			Label label = new Label(group, SWT.NONE);
			label.setText("Website");
			label.setLayoutData(d);

			d = new GridData(GridData.FILL_HORIZONTAL);
			d.verticalSpan = 1;
			d.horizontalSpan = 1;

			website = new Text(group, SWT.BORDER);
			website.setLayoutData(d);
		}
		return parent;
	}

	private Composite createClasspathPane(Composite parent) {
		GridData d = null;

		d = new GridData(GridData.FILL_BOTH);
		d.verticalSpan = 1;
		d.horizontalSpan = columns;

		GridLayout layout = new GridLayout();
		layout.makeColumnsEqualWidth = false;
		layout.numColumns = 2;
		// layout.marginWidth = 0;

		Group group = new Group(parent, SWT.NONE);
		group.setLayout(layout);
		group.setLayoutData(d);
		group.setText("Class Path");

		{
			d = new GridData(GridData.FILL_BOTH);
			d.verticalSpan = 1;
			d.horizontalSpan = 1;

			Composite c = new Composite(group, SWT.NONE);
			c.setLayoutData(d);
			c.setLayout(new FillLayout());

			classpath = new ListViewer(c);
			classpath.setLabelProvider(new LabelProvider() {
				@Override
				public String getText(Object element) {
					return ((File) element).getAbsolutePath();
				}

			});
			classpath.setContentProvider(new ArrayContentProvider());
		}
		{
			d = new GridData(GridData.FILL_VERTICAL);
			d.verticalSpan = 1;
			d.horizontalSpan = 1;

			GridLayout buttonsLayout = new GridLayout();
			buttonsLayout.makeColumnsEqualWidth = true;
			buttonsLayout.numColumns = 1;
			buttonsLayout.marginWidth = 0;
			buttonsLayout.marginHeight = 0;

			Composite buttons = new Composite(group, SWT.NONE);
			buttons.setLayout(buttonsLayout);
			buttons.setLayoutData(d);

			{
				d = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
				d.verticalSpan = 1;
				d.horizontalSpan = 1;

				addFile = new Button(buttons, SWT.PUSH);
				addFile.setText("Add File");
				addFile.setLayoutData(d);
				addFile.addSelectionListener(new AddHandler(this, true));
			}
			{
				d = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
				d.verticalSpan = 1;
				d.horizontalSpan = 1;

				addFolder = new Button(buttons, SWT.PUSH);
				addFolder.setText("Add Folder");
				addFolder.setLayoutData(d);
				addFolder.addSelectionListener(new AddHandler(this, false));
			}
			{
				d = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
				d.verticalSpan = 1;
				d.horizontalSpan = 1;

				remove = new Button(buttons, SWT.PUSH);
				remove.setText("Remove");
				remove.setLayoutData(d);
				remove.addSelectionListener(new RemoveHandler(this));
			}
			{
				d = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
				d.verticalSpan = 1;
				d.horizontalSpan = 1;

				listDrivers = new Button(buttons, SWT.PUSH);
				listDrivers.setText("List Drivers");
				listDrivers.setLayoutData(d);
				listDrivers.addSelectionListener(new ListDriversHandler(this));
			}
		}
		return parent;
	}

	private Composite createClassNamePane(Composite parent) {
		GridData d = null;

		d = new GridData(GridData.FILL_HORIZONTAL);
		d.verticalSpan = 1;
		d.horizontalSpan = columns;

		GridLayout layout = new GridLayout();
		layout.makeColumnsEqualWidth = false;
		layout.numColumns = 2;

		Composite c = new Composite(parent, SWT.NONE);
		c.setLayoutData(d);
		c.setLayout(layout);

		{
			d = new GridData();
			d.verticalSpan = 1;
			d.horizontalSpan = 1;

			Label label = new Label(c, SWT.NONE);
			label.setText("Class Name");
			label.setLayoutData(d);

			d = new GridData(GridData.FILL_HORIZONTAL);
			d.verticalSpan = 1;
			d.horizontalSpan = 1;
			d.grabExcessHorizontalSpace = true;

			className = new Combo(c, SWT.READ_ONLY | SWT.DROP_DOWN);
			className.setLayoutData(d);
			className.addSelectionListener(new SelectionAdapter() {
				@Override
				public void widgetSelected(SelectionEvent e) {
					selectDriver(className.getText());
				}
			});
		}
		return parent;
	}
}
